package com.example.untitled1


import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.*
import android.bluetooth.BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
import android.bluetooth.le.*
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import com.example.untitled1.BleScanResult
import com.google.gson.Gson
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.*
import java.util.*
import java.util.concurrent.LinkedBlockingQueue


@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@SuppressLint("MissingPermission")
class BleManager(private var context: Context) {

    private val bluetoothAdapter: BluetoothAdapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
    private val gattClientCallback:GattClientCallback
    private val filters:MutableList<ScanFilter> = mutableListOf()
    private val bluetoothLeScanner: BluetoothLeScanner? = bluetoothAdapter.bluetoothLeScanner
    private var scanClientCallback:ScanCallback? = null
    private val bluetoothGattS: MutableMap<String,BluetoothGatt?> = mutableMapOf()
    private var deviceName = ""
    var scanResult:MutableMap<String,ScanResult> = mutableMapOf()
    var bleScanResult:MutableMap<String, BleScanResult> = mutableMapOf()
    private lateinit var channel: MethodChannel
    private var falseNumber = 0

    var statusBle = "已连接"

    init {
//        filters.add(ScanFilter.Builder()
//            .setServiceUuid(ParcelUuid.fromString("0000ac50-1212-efde-1523-785fedbeda25"))
//            .build())
        gattClientCallback = GattClientCallback()
        @OptIn(DelicateCoroutinesApi::class)
        GlobalScope.launch(Dispatchers.IO) {
            while (true) {
                val take = linked.take()
                var result = false
                while (!result) {
                    result = sendData(take)
                }
            }
        }
    }



    fun scan(channel: MethodChannel) {
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED) {
            this.channel = channel
            scanClientCallback = ScanClientCallback()
            bluetoothLeScanner?.startScan(filters, ScanSettings.Builder().build(),scanClientCallback)
        }
    }

    fun connect(address:String?){
        val result:ScanResult = scanResult[address] ?: error("Scan 结果 未找到")
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                result.device.connectGatt(context,false,gattClientCallback,BluetoothDevice.TRANSPORT_LE)
            }else{
                result.device.connectGatt(context,false,gattClientCallback)
            }
        }
    }

    private val linked:LinkedBlockingQueue<ByteArray> = LinkedBlockingQueue<ByteArray>()
    private var breakUp = 509
    private var separate = 0
    private var add = 0
    private var data:ByteArray = byteArrayOf()

    //拆包
    fun separate(data:ByteArray){
        if(this.data.isNotEmpty()){
            Log.d("设备返回的信息","上一包数据发送中")
            return
        }
        falseNumber = 0
        separate = if ( data.size % breakUp == 0 ) { data.size / breakUp } else { data.size / breakUp + 1 }
        this.data = data
        add = 0
        linked.put(data.copyOfRange(0, breakUp.coerceAtMost(data.size)))
        statusBle = System.currentTimeMillis().toString();
    }

    private fun sendData(data:ByteArray?):Boolean {
        val bluetoothGatt = bluetoothGattS[deviceName] ?: return false
        //获取蓝牙GATT服务
        val gattService: BluetoothGattService = bluetoothGatt.getService(UUID.fromString("0000AC50-1212-EFDE-1523-785FEDBEDA25"))
        //GATT特性：用于构建 GATT 服务的基本数据元素
        val characteristic = gattService.getCharacteristic(UUID.fromString("0000AC54-1212-EFDE-1523-785FEDBEDA25"))
        //设置此特性的本地存储值。
        characteristic.value = data
        //设置此特征的写入类型
        //写入特性，请求远程设备确认
//        characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
//        Log.d("设备返回的信息","WRITE_TYPE_DEFAULT")
        //写入特性，无需远程设备响应
        characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
        Log.d("设备返回的信息","WRITE_TYPE_NO_RESPONSE")
        //写入到远程蓝牙设备
        val result = bluetoothGatt.writeCharacteristic(characteristic)
        statusBle = "发送大小${data?.size} 发送结果：$result 剩余${separate-add} ${System.currentTimeMillis()}\n" + statusBle
        if(!result){
            falseNumber++
        }
        Handler(Looper.getMainLooper()).post{
            channel.invokeMethod("device", mapOf("status" to statusBle))
        }
        return result
    }

    inner class ScanClientCallback :ScanCallback() {
        //扫描结果
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            super.onScanResult(callbackType, result)
            if(result.device.name==null){
                return
            }
            if(result.device.name.length< 3){
                return
            }
            scanResult[result.device.address] = result
            bleScanResult[result.device.address] = BleScanResult(result.device.address,result.rssi,result.device.name)
            Handler(Looper.getMainLooper()).post{
                channel.invokeMethod("scanResult", mapOf("result" to Gson().toJson(bleScanResult.values)));
            }
        }
        override fun onBatchScanResults(results: List<ScanResult?>?) {
            super.onBatchScanResults(results)
        }
    }


    @SuppressLint("MissingPermission")
    inner class GattClientCallback : BluetoothGattCallback() {

        //指示GATT客户端何时连接到远程GATT服务器/从远程GATT服务器断开连接的回调
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            if(status ==BluetoothGatt.GATT_SUCCESS){
                if(newState ==BluetoothProfile.STATE_CONNECTED){
                    gatt?.also {
                        //获取服务
                        it.discoverServices()
                        deviceName = it.device.name
                        bluetoothGattS[deviceName] = gatt
                        statusBle += deviceName
                        Handler(Looper.getMainLooper()).post{
                            channel.invokeMethod("device", mapOf("status" to statusBle))
                        }
                    }
                }
            }
            if(newState ==BluetoothProfile.STATE_DISCONNECTED){

            }
        }

        //发现新服务时调用回调
        override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
            super.onServicesDiscovered(gatt, status)
            //通知UUID
            val gattCharacteristic: BluetoothGattCharacteristic? =
                gatt?.getService(UUID.fromString("0000ac50-1212-efde-1523-785fedbeda25"))
                    ?.getCharacteristic(UUID.fromString("0000ac51-1212-efde-1523-785fedbeda25"))
            enableNotification(gatt, true, gattCharacteristic)
        }


        //mtu设置成功
        override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
            super.onMtuChanged(gatt, mtu, status)
            statusBle+= "->mtu$mtu"
            Handler(Looper.getMainLooper()).post{
                channel.invokeMethod("device", mapOf("status" to statusBle))
            }
        }

        //通知设置成功
        override fun onDescriptorWrite(
            gatt: BluetoothGatt?,
            descriptor: BluetoothGattDescriptor?,
            status: Int
        ) {
            super.onDescriptorWrite(gatt, descriptor, status)
            statusBle+="->设置通知成功"
            Handler(Looper.getMainLooper()).post{
                channel.invokeMethod("device", mapOf("status" to statusBle))
            }
            //设置mtu
            gatt?.requestMtu(512)
        }

        //远程特征通知触发了回调
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?
        ) {
            super.onCharacteristicChanged(gatt, characteristic)
            //设备返回的信息 jieli
            Log.d("设备返回的信息","信息剩余${separate-add}${characteristic?.value}")

        }

        //特征读取操作结果的回调
        override fun onCharacteristicRead(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?,
            status: Int
        ) {
            super.onCharacteristicRead(gatt, characteristic, status)
        }

        //特征写操作结果的回调
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?,
            status: Int
        ) {
            super.onCharacteristicWrite(gatt, characteristic, status)
            if(add>= separate-1)  {
                data= byteArrayOf()
                Log.d("设备返回的信息","最后一包数据发送完成  失败：${falseNumber}")
                return
            }
            linked.put(data.copyOfRange( ++add * breakUp, ((add + 1) * breakUp).coerceAtMost(data.size)))
        }

        //回调报告描述符读取操作的结果
        override fun onDescriptorRead(
            gatt: BluetoothGatt?,
            descriptor: BluetoothGattDescriptor?,
            status: Int
        ) {
            super.onDescriptorRead(gatt, descriptor, status)
        }

        override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
            super.onReadRemoteRssi(gatt, rssi, status)
        }
    }

    //是否开启通知
    private fun enableNotification(bluetoothGatt: BluetoothGatt?, enable: Boolean, characteristic: BluetoothGattCharacteristic?) {
        if (bluetoothGatt == null || characteristic == null) {
            return
        }
        if (!bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
            return
        }
        //获取到Notify当中的Descriptor通道  然后再进行注册
        val clientConfigs = characteristic.descriptors
        if (clientConfigs == null || clientConfigs.size == 0) {
            return
        }
        if (enable) {
            for (clientConfig in clientConfigs) {
                clientConfig.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                bluetoothGatt.writeDescriptor(clientConfig)
            }
        } else {
            for (clientConfig in clientConfigs) {
                clientConfig.value = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
                bluetoothGatt.writeDescriptor(clientConfig)
            }
        }
    }

}


